defmodule MessageServer.MessageAdapter do
    alias MessageServer.Repo
    alias MessageServer.MessageContent
    alias MessageServer.MessageContentAdapter
    alias MessageServer.Message
    require Ecto.Query
    require Logger

    @doc """
    Create message

    usage:

    iex> params = %{type: 1, srcid: 1, dest: 2}
    iex> create_msg params, 2
    """
    def create_msg(params, msgid) do
        newParams = params |> Map.put(:contentid, msgid)
        changeset = %Message{} |> Message.changeset(newParams)
        if changeset.valid? do
            case Repo.insert(changeset) do
                {:ok, message} ->
                     message
                {:error, changeset} ->
                    errormsg = Message.getErrorMsg(changeset.errors, %{})
                    IO.inspect errormsg
                    nil
            end
        else
            errormsg = Message.getErrorMsg(changeset.errors, %{})
            IO.inspect errormsg
            nil
        end
    end

    def find_msg(id) do
        Message |> Repo.get(id)
    end

    def find_user_unread_msg(srcid, destid) do
          messagelist  = Message 
                                |> Ecto.Query.where(srcid: ^srcid) 
                                |> Ecto.Query.where(destid: ^destid)
                                |> Ecto.Query.where(status: false)
                                |> Repo.all
        msglist = Enum.filter_map(messagelist,
                     fn msg -> (msg.type != 1) end, 
                     fn msg -> 
                         {:ok, dt} = msg.inserted_at |> DateTime.from_naive("Etc/UTC")
                         ii = DateTime.to_unix dt

                         %{type: msg.type, msgid: msg.id, timestamps: ii}
                         end)
        {:ok, %{unreadmsg: msglist} }
    end

    def getMsgDetail(id) do
        MessageContentAdapter.find_message_content(id)
    end

    def find_user_msg(id) do

        case find_msg(id) do
            nil ->
                {:error, "not such msg id"}
            msg ->
                cond do
                    (msg.type == 2) && (msg.status == true) ->
                        {:error, "already handle"}
                    (msg.type == 2) && (msg.status == false) ->
                            changeset = Message.changeset(msg, %{status: true}) 
                            Repo.update(changeset)
                            find_user_msg(msg.contentid)
                    true ->
                        case  MessageContentAdapter.find_message_content(msg.contentid) do
                            nil -> 
                                {:error, "sth wrong, but i don't know"}
                            msgcontent ->
                                {:ok, dt} = msgcontent.inserted_at |> DateTime.from_naive("Etc/UTC")
                                ii = DateTime.to_unix dt
                                changeset = Message.changeset(msg, %{status: true}) 
                                Repo.update(changeset)
                                {:ok, %{msg: %{content: msgcontent.content, timestamps: ii, srcid: msg.srcid, destid: msg.destid} } }
                        end
                end
        end
    end
    @doc """
    usage:

    iex> params = %{type:2, srcid: 1}
    iex> destkey = [1, 3, 4, 5]
    iex> broadcast params, destkey, 1
    """
    def broadcast(params, key, msgid) when is_list(key) do
        newParams = params |> Map.put(:contentid, msgid)
        Repo.transaction(fn -> broadcast(newParams, key) end)
    end

    def broadcast(params, []) do

    end

    def broadcast(params, destlist) when is_list(destlist) do
        [destid | next] = destlist
        newParams = params |> Map.put(:destid, destid)
        %Message{} 
        |> Message.changeset(newParams)
        |> Repo.insert
        broadcast(params, next)
    end

    def update_msg(id, params) do
        case Message |> Repo.get(id) do
            nil ->
                {:error, "not find msg #{id}!"}
            msg ->
                msg
                |> Message.changeset(params)
                |> Repo.update
        end
    end
end